﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GodPl.GameObjects.Creatures;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;

namespace GodPl.Parser
{
    public class GodPlCompiler
    {

        private static CompilerResults results;

        public static bool HasCode
        {
            get { return (results != null); }
        }

        public static void CompileUserBriyyaUpdater(string sourceCode)
        {
            CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;
            parameters.IncludeDebugInformation = false;

            Type[] neededTypes =
            {
                typeof(IBriyyaUpdater),
                typeof(System.Linq.Enumerable),
                typeof(Microsoft.Xna.Framework.GameTime),
                typeof(Microsoft.Xna.Framework.Graphics.Color)
            };

            foreach (Type type in neededTypes)
            {
                string location = Assembly.GetAssembly(type).Location;
                string fullPath = Path.GetFullPath(location);
                parameters.ReferencedAssemblies.Add(fullPath);
            }

            results = provider.CompileAssemblyFromSource(parameters, new string[] { sourceCode });

            if (results.Errors.Count == 0)
            {
                // Test creating an instance
                IBriyyaUpdater newInstance = (IBriyyaUpdater)FindInterface(results.CompiledAssembly, "IBriyyaUpdater");
            }
            else
            {
                string exceptions = "";
                foreach(CompilerError error in results.Errors)
                {
                    exceptions += error.ToString() + "\r\n\r\n";
                }
                results = null;
                throw new ApplicationException("Compilation errors:\r\n\r\n" + exceptions);
            }
        }

        public static IBriyyaUpdater GetNewInstance()
        {
            if (!HasCode) return null;

            IBriyyaUpdater newInstance = (IBriyyaUpdater)FindInterface(results.CompiledAssembly, "IBriyyaUpdater");
            return newInstance;
        }

        private static object FindInterface(Assembly assembly, string interfaceName)
        {
            foreach (Type type in assembly.GetTypes())
            {
                if (type.GetInterface(interfaceName, true) != null)
                {
                    return assembly.CreateInstance(type.FullName);
                }
            }
            return null;
        }
    }
}
